#pragma once
#include <math.h>
#include "Vector3.h"
#include "Vector4.h"

namespace lib3dw
{
	struct Matrix4x4 
	{
		Vector4 rows[4];

		Matrix4x4()
		{
			rows[0] = Vector4(1.0, 0.0, 0.0, 0.0);
			rows[1] = Vector4(0.0, 1.0, 0.0, 0.0);
			rows[2] = Vector4(0.0, 0.0, 1.0, 0.0);
			rows[3] = Vector4(0.0, 0.0, 0.0, 1.0);
		}

		Matrix4x4(const Vector4 &row0, const Vector4 &row1, const Vector4 &row2, const Vector4 &row3)
		{
			rows[0] = row0;
			rows[1] = row1;
			rows[2] = row2;
			rows[3] = row3;
		}

		Matrix4x4(const float m00, const float m01, const float m02, const float m03,
			const float m10, const float m11, const float m12, const float m13,
			const float m20, const float m21, const float m22, const float m23,
			const float m30, const float m31, const float m32, const float m33)
		{
			rows[0] = Vector4(m00, m01, m02, m03);
			rows[1] = Vector4(m10, m11, m12, m13);
			rows[2] = Vector4(m20, m21, m22, m23);
			rows[3] = Vector4(m30, m31, m32, m33);
		}

		operator const float *() const
		{
			return (const float *) rows;
		}

		void translate(const Vector3 &v);
		static Matrix4x4 translate(const float x, const float y, const float z);
		static Matrix4x4 scale(const float x, const float y, const float z);
		static Matrix4x4 rotateX(const float a);
		static Matrix4x4 rotateY(const float a);
		static Matrix4x4 rotateZ(const float a);
	};

	Matrix4x4 operator + (const Matrix4x4 &m, const Matrix4x4 &n);
	Matrix4x4 operator - (const Matrix4x4 &m, const Matrix4x4 &n);
	Matrix4x4 operator - (const Matrix4x4 &m);
	Matrix4x4 operator * (const Matrix4x4 &m, const Matrix4x4 &n);
	Vector4 operator * (const Matrix4x4 &m, const Vector4 &v);
	Matrix4x4 operator * (const Matrix4x4 &m, const float x);
}